home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fritz: All Fritz
/
All Fritz.zip
/
All Fritz
/
FILES
/
DATATION
/
QPARSER.LZH
/
CALCUTIL.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1985-07-26
|
4KB
|
127 lines
{ CALCUTIL: Calculator Utilities. }
{ Copyright (C) 1984 by QCAD Systems Inc., All Rights Reserved. }
{******************}
procedure WRITE_VALUE(R: real);
{ writes r to the screen in a 'reasonable' format. must resort
to Turbo's exponential notation in extreme cases. }
const
MIN_MAGNITUDE = -38;
{ Turbo Pascal has roughly 12 decimal digits of precision;
keep the last one as a guard digit. }
PRECISION = 11;
var
MAGNITUDE: integer;
FRACTION: real;
FUZZ: real; { number to compare against for roundoff }
{..................}
procedure WRITE_FRACTION(FRACTION: real; DIGITS: integer);
{ chunk out zero or more digits of the fraction, until either
the digit count gives out, or we run into the fuzz. }
begin
while (abs(fraction) > fuzz) and (digits > 0) do begin
fraction := fraction * 10.0;
write(trunc(fraction):1);
fuzz := fuzz * 10.0;
digits := digits-1;
fraction := frac(fraction)
end
end;
begin { write_value }
{ first, establish some useful information about R. }
if r = 0.0 then
magnitude := 0
else
magnitude := trunc(ln(abs(r))/ln(10.0));
if magnitude-precision >= min_magnitude then begin
fuzz := exp((magnitude-precision+1)*ln(10.0));
{ Turbo reals tend to err toward zero; use the fuzz to
compensate for this effect. }
if r<0.0 then
r := r-fuzz
else if r>0.0 then
r := r+fuzz
end
else
fuzz := 0.0;
fraction := abs(frac(r));
{ now, decide what to do with R. }
if (abs(r) >= maxint) or (magnitude < -3) then
{ big enough or small enough for a possible loss of precision:
use exponential notation. }
write(r)
else if fraction < fuzz then
{ essentially whole number of small magnitude }
write(trunc(r):1)
else begin
{ real number in ddd.ddd format. }
if (-1.0 < r) and (r < 0.0) then
write('-'); { trunc eliminates minus sign for these numbers }
write(trunc(r):1, '.');
write_fraction(fraction, precision-magnitude)
end
end { write_value };
{******************}
procedure EVAL_BINOP(OP: operator; OPND1, OPND2: semrecp;
RESULT: semrecp);
{ evaluate the given binary operator, setting up the result
semantic record with the resulting value. if there is an
error, result will generally contain a non-value (because
it is set up to be 'other' rather than 'float' by default).
most of the code here is for error handling. }
var V1, V2: real; { operand values }
SEM_TYPE: semtype; { type of result }
begin
if opnd2 = nil then begin
{ actually, its a unary operator }
if opnd1^.semt = float then begin
case op of
uminus: result^.rval := -opnd1^.rval;
ELSE error('internal problems in eval_binop')
end;
result^.semt := float
end
end
else if opnd1^.semt <> float then
result^ := opnd2^
else if opnd2^.semt <> float then
result^ := opnd1^
else begin
{ both values are good }
v1 := opnd1^.rval;
v2 := opnd2^.rval;
sem_type := float;
case op of
divide: if v2 <> 0.0 then
v1 := v1/v2
else begin
write('Attempt to divide ');
write_value(v1);
writeln(' by zero.');
sem_type := other
end;
mpy: v1 := v1*v2;
plus: v1 := v1+v2;
minus: v1 := v1-v2;
end;
result^.semt := sem_type;
result^.rval := v1
end
end;
{******************}
procedure INIT_SEM;
{ No semantics initialization needed. }
begin
end;
{******************}
procedure END_SEM;
{ No semantics conclusion needed. }
begin
end;